/** @file

Copyright (c) 2006-2023, Kunlun BIOS, Kunlun Technology (Beijing) Co., Ltd.. All
Rights Reserved.

You may not reproduce, distribute, publish, display, perform, modify, adapt,
transmit, broadcast, present, recite, release, license or otherwise exploit
any part of this publication in any form, by any means, without the prior
written permission of Kunlun Technology (Beijing) Co., Ltd..

Module Name:OemServicesLib


Abstract:


Revision History:

**/

#include <Uefi.h>
#include <Library/OemServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>

#include <Protocol/PciIo.h>

/**
  Init X100 and get the version.

  @retval     EFI_SUCCESS.      Opertion is successful.
  @retval     others.      Opertion is unsuccessful.

**/
EFI_STATUS
InitX100Version(
  VOID
  )
{
  UINT32               Status;
  UINTN                NumOfPciHandles;
  EFI_HANDLE*          HandleBuffer;
  EFI_PCI_IO_PROTOCOL* PciIo;
  UINT32               Index;
  UINT32               VidDid;
  UINT16               Version;

  Status = 0;
  NumOfPciHandles = 0;
  HandleBuffer = NULL;
  Status = gBS->LocateHandleBuffer(
                                  ByProtocol,
                                  &gEfiPciIoProtocolGuid,
                                  NULL,
                                  &NumOfPciHandles,
                                  &HandleBuffer
                                  );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  for (Index = 0; Index < NumOfPciHandles; Index++) {
    Status = gBS->HandleProtocol(
                                HandleBuffer[Index],
                                &gEfiPciIoProtocolGuid,
                                (VOID**)&PciIo
                                );
    if (!EFI_ERROR(Status)) {
      PciIo->Pci.Read(
                     PciIo,
                     EfiPciIoWidthUint32,
                     0x0,
                     1,
                     &VidDid
                     );

      DEBUG ((EFI_D_INFO, "VidDid %x\n", VidDid));
      if (VidDid == 0xdc201db7) {
        Status = PciIo->Pci.Read(
                                PciIo,
                                EfiPciIoWidthUint16,
                                0x2e,
                                1,
                                &Version
                                );
        DEBUG((EFI_D_INFO, "X100Version:[0x%04x]\n", Version >> 8));
        if (!EFI_ERROR(Status)) {
          //The upper four bits of the high byte represent the major version,The lower four digits indicate the minor version
          Version = Version >> 8;
          PcdSetEx16S(&gEfiKunlunBdsPkgTokenSpaceGuid, PcdGetX100Version, Version);
          break;
        }
      }
    }
  }

  if (HandleBuffer) {
    gBS->FreePool(HandleBuffer);
  }

  return Status;
}

